home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-04-23 | 9.1 KB | 259 lines | [TEXT/MPS ] |
- //========================================================================================
- //
- // File: Part.cpp
- // Release Version: $ ODF 1 $
- //
- // Copyright: (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
- //
- //========================================================================================
-
- /*
- To find portions of code dealing with code Cyberdog support, search for CYBERDOG.
- This sample has a simple text model; the code is tagged with CONTENTDATA.
- Some constants *must* be changed by you to make a proper part. Search for MUSTCHANGE
- Some threaded stuff is delimited by USETHREADSFLAG but is not finished in this version
- of the code base.
- */
-
- #include "Part.h"
- #include "Frame.h"
- #include "Define.h"
- #include "Binding.h"
-
- #include "Cyberdog.h"
- #include "CyberSession.xh"
- #include "CyberStream.xh"
- #include "CyberItem.xh"
-
- #include "FWContxt.h"
- #include "FWIters.h"
-
- #ifdef FW_BUILD_MAC
- #pragma segment CPart
- #endif
-
- FW_DEFINE_AUTO(CPart)
-
- /*----------------------------------------------------------------------------------------
- Utilities
- ----------------------------------------------------------------------------------------*/
-
- static void ImmediateRedrawPresentation (Environment* ev, FW_CPresentation* p)
- {
- FW_CPresentationFrameIterator piter (ev, p);
- for (FW_CFrame* frame = piter.First(ev); piter.IsNotComplete(ev); frame = piter.Next(ev)) {
- FW_CFrameFacetIterator fiter (ev, frame);
- for (ODFacet* facet = (ODFacet*) fiter.First(ev); fiter.IsNotComplete(ev); facet = fiter.Next(ev)) {
- FW_CViewContext gc (ev, frame, facet, nil);
- ((CFrame*)frame)->DrawUpdate (ev, gc);
- }
- }
- }
-
- //----------------------------------------------------------------------------------------
- // Standard Part Support
- //----------------------------------------------------------------------------------------
-
- CPart::CPart(ODPart* odPart)
- : FW_CPart(odPart, FW_gInstance, kPartInfoID)
- , FW_MCyberPart (this) // CYBERDOG
- #if !USETHREADSFLAG
- , FW_CIdler (this, 6) // idling 10 times a second should be Ok
- , fStream (nil)
- #endif
- , fDownloadedText (nil)
- {
- }
-
- CPart::~CPart()
- {
- ::DisposeHandle (fDownloadedText);
- }
-
- void CPart::Initialize(Environment* ev)
- {
- FW_CPart::Initialize (ev);
- FW_MCyberPart::Initialize (ev);// CYBERDOG
- fPresentation = RegisterPresentation(ev, kODPresDefault, TRUE);
-
- // I think it's simpler to have a 0-length handle than a null handle
- fDownloadedText = ::NewHandle(0);
-
- // RegisterIdle (ev); // HACK to work around an ODF R1c9 bug
- }
-
- FW_CFrame* CPart::NewFrame(Environment* ev,
- ODFrame* odFrame,
- FW_CPresentation* presentation,
- FW_Boolean fromStorage)
- {
- FW_UNUSED(presentation);
- FW_UNUSED(fromStorage);
-
- return FW_NEW(CFrame, (ev, odFrame, presentation, this));
- }
-
- FW_CContent* CPart::NewPartContent(Environment* ev)
- {
- return NULL;
- }
-
- void CPart::ExternalizeContent (Environment* ev, ODStorageUnit* su, FW_CCloneInfo* cloneInfo)
- {
- // Before calling ExternalizeContent, FW_CODPart calls PrivCleanseContentProperty.
- // FW_CPart::ExternalizeContent then calls ClearPartStorage. These amount to an
- // expensize ODSURemoveProperty. RFE
- ODSURemoveProperty (ev, su, kODPropContents);
-
- // Save content. Pure text, no other data, to make sure our data can be read by any other part.
- ODSUForceFocus (ev, su, kODPropContents, kKind);
- FW_PStorageUnitSink sink (ev, su, kODPropContents, kKind);
- FW_CAcquireLockedSystemHandle locked (fDownloadedText);
- sink->Write (ev, *fDownloadedText, GetHandleSize(fDownloadedText));
- }
-
- void CPart::InternalizeContent(Environment* ev, ODStorageUnit* su, FW_CCloneInfo* cloneInfo)
- {
- // Read our content (if any).
- if (ODSUExistsThenFocus (ev, su, kODPropContents, kKind)
- || ODSUExistsThenFocus (ev, su, kODPropContents, FW_CPart::gMacTEXTDataType)) {
- Size size = su->GetSize (ev);
- ::SetHandleSize (fDownloadedText, size);
- FW_CAcquireLockedSystemHandle locked (fDownloadedText);
- FW_PStorageUnitSink sink (ev, su, kODPropContents, kKind);
- sink->Read (ev, *fDownloadedText, size);
- // FW_CByteArray bytes;
- // su->GetValue (ev, size, bytes);
- // bytes.CopyBuffer (*fDownloadedText, size);
- }
- else if (ODSUExistsThenFocus (ev, su, kODPropContents, FW_CPart::gMacTEXTFileType)) {
- }
- }
-
- /*----------------------------------------------------------------------------------------
- CYBERDOG
-
- You need to change DoIdle/LoadCyberItem to read your content from the network.
-
- DoSetCyberItem is called when you need to read a CyberItem. It starts idling,
- and you will read the data in DoIdle. If you are using threads (preferred but not
- quite handled properly by Cyberdog yet), then you will do the work in LoadCyberItem.
-
- Note that you must call inherited to get the default behavior of OpenCyberItem as
- well. Navigator-aware parts will not call inherited but will do things differently.
- ----------------------------------------------------------------------------------------*/
-
- void CPart::DoSetCyberItem (Environment* ev, CyberItem* newItem, ParameterSet* parameters)
- {
- // CYBERDOG - you don't need to change this method
-
- #if !USETHREADSFLAG
- // Create the stream and start idling. We read during idles. After we
- // have all the data we'll delete the stream and stop idling.
- fStream = newItem->CreateCyberStream (ev);
- RegisterIdle (ev); // work-around for bug in ODF R1c9
- ::SetHandleSize (fDownloadedText, 0);
- #else
- // Create a new thread to read the data. It won't start reading until shortly after
- // we return from this method, so we can't pass in any stack-based parameters.
- FW_NewThread (&LoadCyberItem, this);
- #endif
- }
-
- void CPart::HandleOpenCyberItem (Environment* ev, CyberItem* item, ODPart* openerPart, ParameterSet* how)
- {
- // If you want to be a standard Cyber-savvy part then you must call inherited to get
- // the default behavior. Navigator-savvy parts will do things differently (XXX to do!)
- FW_MCyberPart::HandleOpenCyberItem (ev, item, openerPart, how);
- }
-
- #if !USETHREADSFLAG
-
- FW_Boolean CPart::DoIdle (Environment* ev, const FW_CNullEvent& event)
- {
- if (fStream) {
- short status = fStream->GetStreamStatus (ev);
- if (status & kCDDataAvailable) {
- Size oldSize = ::GetHandleSize (fDownloadedText);
- FW_CCyberBuffer ab (ev, fStream);
- // CONTENTDATA - change this portion to deal with your data form
- // Add any data available to the text handle, and redraw it
- ::SetHandleSize (fDownloadedText, oldSize + ab.GetSize());
- if (::MemError()) // XXX what's the best way to report an error from an idle method?
- status = kCDErrorOccurred;
- else
- memcpy (*fDownloadedText + oldSize, ab.GetBuffer(), ab.GetSize());
- // Draw the new data right now
- ImmediateRedrawPresentation (ev, fPresentation);
- }
-
- if (status & FW_kCyberStreamDone) {
- fStream = nil; // smart pointer, will call Abort if necessary automatically
- UnregisterIdle (ev); // work-around for bug in ODF R1c9
- }
- }
-
- return false; // let other idlers get time also XXX need FW_kContinueEvent!
- }
-
- #else
-
- pascal void* CPart::LoadCyberItem (void* selfCPart)
- {
- // XXX this method probably does not compile! Threads support is broken in
- // Cyberdog at this moment and therefore this sample hasn't been updated for it.
- // Check the ODF web site (www.devtools.apple.com/odf) for updates.
-
- CPart* self = (CPart*) selfCPart;
- Environment* ev = somGetGlobalEnvironment();
-
- // Note this is a static method. "this" is passed in from HandleOpenCyberItem/NewThread
-
- CyberItem* item = self->CurrentCyberItem();
- CyberStream* cStream = item->CreateCyberStream (ev);
- FW_CCyberSink sink (cStream);
-
- // Note that we're not trying to read any specific number of bytes of data. That
- // could cause us to sleep. However, if there isn't *any* data, then we will sleep
- // until at least one byte arrives.
-
- // We don't need to deal with error handling at all here. An error causes an
- // exception to be thrown, and all our nice stack-based objects delete themselves.
-
- long total = 0;
- long available;
- while (available = sink.GetAvailableBytes (FW_CCyberSink::kSleepIfNoData)) {
- // CONTENTDATA - change this portion to deal with your data form
- // We'll download and display whatever is available.
- ::SetHandleSize (self->fDownloadedText, total + available);
- ::HLock(self->fDownloadedText);
- sink.Read (*self->fDownloadedText + total, available);
- ::HUnlock (self->fDownloadedText);
- total += available;
- // Draw the new data right now
- ImmediateRedrawPresentation (self->fPresentation);
- }
-
- return nil;
- }
-
- #endif
-
- FW_CEventDispatcher* CPart::PrivNewEventDispatcher(Environment *ev)
- {
- // CYBERDOG - you do not need need to change this method
-
- // Cyberdog goes to considerable lengths to work around OpenDoc problems. One
- // of these is that OpenDoc wants to put everything in a Bento document.
- // Cyberdog makes it's own Draft subclass which is not disk based, and
- // instantiates all parts into that. Unfortunately this is NOT transparent. We
- // are required to let Cyberdog close windows for any of these parts; if
- // OpenDoc sees them it gets very confused.
- // This means we need to intercept close-box and command-W events. Command-W
- // is easy, but close-box events require us to subclass ODF's event dispatcher
- // class. This will be fixed for the next release of ODF.
-
- return FW_MCyberPart::MakeEventDispatcher (ev);
- }
-
-